/**
 * 文件名：****.java
 * 版权：Copyright Lightkit All Rights Reserved.
 * 描述：*****
 */
package com.lightkits.wms.domain.commons.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.lightkits.common.MessageUtil;
import com.lightkits.common.db.entity.BdOnhandQuantity;
import com.lightkits.common.db.entity.FndPartyBase;
import com.lightkits.common.db.entity.FndWarehouse;
import com.lightkits.common.db.entity.FndWmArea;
import com.lightkits.framework.common.exception.LightKitsBizException;
import com.lightkits.framework.common.model.IResult;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.framework.common.utility.validate.IntegrityValidator;
import com.lightkits.wms.domain.commons.service.WmsCommonsService;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.regex.Pattern;

/**
 * WmsCommonsServiceImpl
 *
 * @author jing.wei@hand-china.com
 * Created on 2019/4/16 19:45
 */
@Service
public class WmsCommonsServiceImpl implements WmsCommonsService {
    /**
     * 负库存校验
     *
     * @param warehouseId 仓库ID 必输
     * @param locationId  货位ID
     * @param adjustQty   调整数量 必输
     * @param uom         单位 必输
     * @return IResult
     */
    @Override
    public IResult checkNegativestock(String warehouseId,
                                      String locationId,
                                      String adjustQty,
                                      String uom) {
        try {
            //校验参数的非空性
            IntegrityValidator.begin().validate(warehouseId, "Warehouse Id")
                    .validate(adjustQty, "Adjust Quantity")
                    .validate(uom, "Uom");
        } catch (LightKitsBizException e) {
            return e.result();
        }
        //校验数字的有效性
        Pattern pattern = Pattern.compile("([1-9]\\d*\\.?\\d*)|(0\\.\\d*[1-9])");
        if (!pattern.matcher(adjustQty).matches()) {
            return IResult.fail("The Adjust Quantity is invalid");
        }
        //仓库货位有效性校验
        IResult result = checkLocationParams(warehouseId, locationId);
        if (!result.isSuccessful()) {
            return result;
        }
        //定制消息（“发出仓库不允许负库存”）
        result = IResult.fail(MessageUtil.getSysMessage("NEGATIVE_STOCK_WAS_NOT_ALLOWED"));
        FndWarehouse warehouse = new FndWarehouse().selectById(warehouseId);

        //判断是否开启负库存
        if (!warehouse.getNegativeFlag()) {
            //判断是否开启货位管理
            if (warehouse.getWmAreaFlag()) {
                //开启货位管理下的货位下的现有量
                List<BdOnhandQuantity> quantities   = new BdOnhandQuantity()
                        .selectList(new EntityWrapper()
                                .eq(BdOnhandQuantity.WM_AREA_ID, locationId)
                                .eq(BdOnhandQuantity.WAREHOUSE_ID, warehouseId)
                                .eq(BdOnhandQuantity.PRIMARY_UOM, uom));

                BigDecimal onHandQty=quantities .stream()
                        .map(BdOnhandQuantity::getQuantity)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                if (onHandQty.compareTo(new BigDecimal(adjustQty)) < 0) {
                    return result;
                }
            } else {
                //没有货位管理下的货位下的现有量
                BigDecimal onHandQty = new BdOnhandQuantity()
                        .selectList(new EntityWrapper()
                                .isNull(BdOnhandQuantity.WM_AREA_ID)
                                .eq(BdOnhandQuantity.WAREHOUSE_ID, warehouseId)
                                .eq(BdOnhandQuantity.PRIMARY_UOM, uom))
                        .stream()
                        .map(BdOnhandQuantity::getQuantity)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                if (onHandQty.compareTo(new BigDecimal(adjustQty)) < 0) {
                    return result;
                }
            }
        }
        return IResult.success();
    }

    /**
     * 仓库货位有效性校验
     *
     * @param warehouseId 仓库Id
     * @param wmAreaId    货位Id
     * @return IResult
     */
    @Override
    public IResult checkLocationParams(String warehouseId, String wmAreaId) {
        //仓库非空校验
        if (ObjectUtil.isNullOrEmpty(warehouseId)) {
            return IResult.fail("the warehouseId is null");
        }
        //仓库有效性校验
        FndWarehouse warehouse = new FndWarehouse().selectById(warehouseId);
        if (ObjectUtil.isEmpty(warehouse)) {
            return IResult.fail("the warehouseId in invalid");
        }
        //消息（“仓库或货位不正确”）
        IResult result = IResult.fail(
                MessageUtil.getSysMessage("WM_AREA_NULL_OR_INVALID"));
        //判断是否开启货位管理
        boolean b = ObjectUtil.isEmpty(warehouse.getWmAreaFlag()) ? false : warehouse.getWmAreaFlag();
        if (b) {
            //开启货位管理下必须有货位
            if (ObjectUtil.isNullOrEmpty(wmAreaId)) {
                return result;
            } else {
                //开启货位管理下货位必须存在且为该仓库下的货位
                FndWmArea wmArea = new FndWmArea().selectById(wmAreaId);
                if (ObjectUtil.isEmpty(wmArea)) {
                    return result;
                }
                if (!warehouseId.equals(wmArea.getWarehouseId().toString())) {
                    return result;
                }
            }
        }
        return IResult.success();
    }

    /**
     * 所有者类型校验
     *
     * @param ownerType 所有者类型
     * @param ownerId   所有者ID
     * @return IResult
     */
    @Override
    public IResult checkOwnerParams(String ownerType, String ownerId) {
        //所有者类型的非空
        if (ObjectUtil.isNullOrEmpty(ownerType)) {
            return IResult.fail("The Owner Type is null");
        }
        if (ownerType.equals("OWN")) {
            return IResult.success();
        }
        IResult result = IResult.fail(MessageUtil.getSysMessage("OWNER_ID_NULL_OR_INVALID"));
        if (ObjectUtil.isNullOrEmpty(ownerId)) {
            return result;
        }

        FndPartyBase partyBase = new FndPartyBase().selectById(ownerId);
        if (ObjectUtil.isEmpty(partyBase)) {
            return result;
        }
        return IResult.success();
    }
}
